/**
 * @file upgrade.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_UPGRADE != 0

#include <stdio.h>

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/
#if UPGRADE_FOTA_GS
extern void fota_init(void);
extern void ui_fota_checkversion(void);
extern void ui_fota_download(void);
extern void ui_fota_startupdater(void);
#endif

/**********************
 *  STATIC PROTOTYPES
 **********************/
static lv_obj_t * upgrade_get_obj(void);
static lv_upgrade_obj_ext_t * upgrade_get_ext(void);
static void upgrade_check_btn_action(lv_obj_t * btn, lv_event_t e);
static void upgrade_confirm_btn_action(lv_obj_t * btn, lv_event_t e);
static void upgrade_cancel_btn_action(lv_obj_t * btn, lv_event_t e);
static void upgrade_update_confirm_create(void);
static void upgrade_no_update_create(void);
static void upgrade_no_update_anim_end(lv_obj_t * anim);
#if !UPGRADE_FOTA_GS
static void upgrade_download_progress_cb(void * para);
#endif
static void upgrade_prepare_destory(lv_obj_t * activity_obj);

//callback function
static void upgrade_check_version_ind(FotaVersionInfo * version);
static void upgrade_download_percent_ind(INT32 percent);  //0-100
static void upgrade_restart_ind(void);
static void upgrade_result_ind(INT32 result);   // 1:success; otherwise:failure

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
***********************/
lv_obj_t * upgrade_create(lv_obj_t * activity_obj)
{
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_UPGRADE;
        activity_ext.create = NULL;
        activity_ext.prepare_destory = upgrade_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(activity_obj == NULL) return NULL;
    }

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(obj == NULL) return NULL;
    lv_watch_obj_set_anim_mode(obj, LV_WATCH_ANIM_NO);

    lv_upgrade_obj_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_upgrade_obj_ext_t));
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;
    ext->state = UGD_STATE_NULL;
    ext->download_timer_id = NULL;

    //title
    lv_obj_t * label_title = lv_label_create(obj, NULL);
    lv_obj_add_style(label_title, LV_LABEL_PART_MAIN, &lv_watch_font20_gray);
    lv_label_set_align(label_title, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_click(label_title, false);
    lv_label_set_text_id(label_title, WATCH_TEXT_ID_SYSTEM_UPG);
    lv_obj_align(label_title, obj, LV_ALIGN_IN_TOP_MID, 0, 10);

    //current version
    lv_obj_t * label_ver1 = lv_label_create(obj, NULL);
    lv_obj_add_style(label_ver1, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_label_set_align(label_ver1, LV_LABEL_ALIGN_LEFT);
    lv_label_set_text_id(label_ver1, WATCH_TEXT_ID_CURRENT_VERSION);
    lv_obj_align(label_ver1, obj, LV_ALIGN_IN_TOP_LEFT, 10, 36);

    lv_obj_t * label_ver2 = lv_label_create(obj, NULL);
    lv_obj_add_style(label_ver2, LV_LABEL_PART_MAIN, &lv_watch_font20_gray);
    lv_label_set_align(label_ver2, LV_LABEL_ALIGN_LEFT);
    lv_label_set_text(label_ver2, app_adaptor_get_version());
    lv_obj_align(label_ver2, label_ver1, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);

    //new version
    lv_obj_t * cont_new_ver = lv_cont_create(obj, NULL);
    lv_obj_add_style(cont_new_ver, LV_LABEL_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(cont_new_ver, LV_HOR_RES, 60);
    lv_obj_align(cont_new_ver, label_ver2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_hidden(cont_new_ver, true);
    ext->cont_new_ver = cont_new_ver;

    lv_obj_t * label_new_ver1 = lv_label_create(cont_new_ver, label_ver1);
    lv_label_set_text_id(label_new_ver1, WATCH_TEXT_ID_NEW_VERSION);
    lv_obj_align(label_new_ver1, label_ver2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 7);

    lv_obj_t * label_new_ver2 = lv_label_create(cont_new_ver, label_ver2);
    lv_label_set_text(label_new_ver2, "");
    lv_obj_align(label_new_ver2, label_new_ver1, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    ext->label_new_ver = label_new_ver2;

    //progress bar
    lv_obj_t * cont_bar = lv_cont_create(obj, NULL);
    lv_obj_add_style(cont_bar, LV_LABEL_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(cont_bar, LV_HOR_RES, 60);
    lv_obj_align(cont_bar, cont_new_ver, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_hidden(cont_bar, true);
    ext->cont_bar = cont_bar;

    lv_obj_t * label_bar = lv_label_create(cont_bar, label_ver1);
    lv_label_set_text_id(label_bar, WATCH_TEXT_ID_DOWNLOAD_PROGRESS);
    lv_obj_align(label_bar, label_new_ver2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 7);

    lv_obj_t * bar = lv_bar_create(cont_bar, NULL);
    lv_obj_set_style_local_bg_color(bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_MAROON);
    lv_obj_set_size(bar, LV_HOR_RES - 25, 30);
    lv_obj_align(bar, label_bar, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_bar_set_value(bar, 0, LV_ANIM_OFF);
    ext->bar = bar;

    //upgrade result
    lv_obj_t * label_result = lv_label_create(obj, NULL);
    lv_obj_add_style(label_result, LV_LABEL_PART_MAIN, &lv_watch_font20_yellow);
    lv_label_set_text_id(label_result, WATCH_TEXT_ID_UPGRADE_FAILED);
    lv_obj_align(label_result, cont_new_ver, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
    lv_obj_set_hidden(label_result, true);
    ext->label_result = label_result;

    //check update button
    lv_obj_t * btn_check = lv_btn_create(obj, NULL);
    lv_obj_set_event_cb(btn_check, upgrade_check_btn_action);
    lv_obj_set_size(btn_check, LV_HOR_RES, 40);
    lv_obj_align(btn_check, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);

    lv_obj_t * label_check = lv_label_create(btn_check, NULL);
    lv_label_set_text_id(label_check, WATCH_TEXT_ID_DETECT_UPDATE);
    lv_obj_add_style(label_check, LV_LABEL_PART_MAIN, &lv_watch_font20);

    watch_set_suspend_enable(false, ACT_ID_UPGRADE, 0);

#if UPGRADE_FOTA_GS
#if 1 //temp code
    static bool init = false;
    if(!init) {
        init = true;
        fota_init();
    }
#endif

    ui_fota_bind(upgrade_check_version_ind,
                 upgrade_download_percent_ind,
                 upgrade_restart_ind,
                 upgrade_result_ind);
#endif

    return obj;
}

void upgrade_create_btn_action(lv_obj_t * btn, lv_event_t e)
{
    (void)btn;

    if(LV_EVENT_CLICKED != e) {
        return;
    }

    lv_obj_t * obj = upgrade_create(NULL);
    LV_ASSERT_MEM(obj);
}

lv_upgrade_state_t upgrade_get_state(void)
{
    lv_upgrade_state_t state = UGD_STATE_NULL;

    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(ext) {
        state = ext->state;
    }

    return state;
}

void upgrade_check_version_ind_handler(FotaVersionInfo * version)
{
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    lv_obj_set_hidden(ext->cont_new_ver, true);
    lv_obj_set_hidden(ext->cont_bar, true);
    lv_obj_set_hidden(ext->label_result, true);

    if((NULL == version) || (NULL == version->versionName)) {
        upgrade_no_update_create();
        ext->state = UGD_STATE_NULL;
    } else {
        lv_label_set_text(ext->label_new_ver, version->versionName);
        upgrade_update_confirm_create();
    }
}

void upgrade_download_percent_ind_handler(INT32 percent)
{
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    lv_bar_set_value(ext->bar, percent, LV_ANIM_OFF);
}

void upgrade_restart_ind_handler(void)
{
#if UPGRADE_FOTA_GS
    ui_fota_startupdater();
#else
    play_anim_power_off();
#endif
}

void upgrade_result_ind_handler(INT32 result)
{
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    ext->state = UGD_STATE_NULL;

    if(1 != result) {   //not success
        lv_obj_set_hidden(ext->cont_new_ver, true);
        lv_obj_set_hidden(ext->cont_bar, true);
        lv_obj_set_hidden(ext->label_result, false);
    }
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static lv_obj_t * upgrade_get_obj(void)
{
    lv_obj_t * watch_obj = NULL;

    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_UPGRADE);
    if(activity_obj) {
        lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    }

    return watch_obj;
}

static lv_upgrade_obj_ext_t * upgrade_get_ext(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_UPGRADE);
    if(activity_obj == NULL) return NULL;

    lv_obj_t * watch_obj;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    if(watch_obj == NULL) return NULL;

    if(watch_obj) {
        lv_upgrade_obj_ext_t  * ext = lv_obj_get_ext_attr(watch_obj);
        return ext;

    }
    return NULL;
}

static void upgrade_check_btn_action(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();

    if(UGD_STATE_NULL != ext->state) {
        return;
    }
    ext->state = UGD_STATE_CV;

    lv_obj_set_hidden(ext->cont_new_ver, true);
    lv_obj_set_hidden(ext->cont_bar, true);
    lv_obj_set_hidden(ext->label_result, true);

#if UPGRADE_FOTA_GS
    ui_fota_checkversion();
#else

    static uint8_t i = 0;

    switch(i) {
        case 0:  //no update
            upgrade_check_version_ind(NULL);
            break;
        case 1: { //has new version
            char version_name[] = "1.2.3";
            FotaVersionInfo * version = (FotaVersionInfo *)Hal_Mem_Alloc(sizeof(FotaVersionInfo));
            Hal_Mem_Set(version, 0, sizeof(FotaVersionInfo));
            version->versionName = (char *)Hal_Mem_Alloc(strlen(version_name) + 1);
            strncpy(version->versionName, version_name, strlen(version_name) + 1);

            upgrade_check_version_ind(version);
        }
        break;
        case 2:  //failure
            upgrade_result_ind(0);
            break;
        default:
            break;
    }

    i++;
    i = i % 3;

#endif
}

static void upgrade_confirm_btn_action(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();

    ext->state = UGD_STATE_DL;
    lv_bar_set_value(ext->bar, 0, LV_ANIM_OFF);
    lv_obj_set_hidden(ext->cont_new_ver, false);
    lv_obj_set_hidden(ext->cont_bar, false);
    lv_obj_set_hidden(ext->label_result, true);
    lv_obj_del(ext->obj_confirm);

#if UPGRADE_FOTA_GS
    ui_fota_download();
#else
    ext->download_timer_id = Hal_Timer_Start(1000, upgrade_download_progress_cb, NULL, 1);
#endif
}

static void upgrade_cancel_btn_action(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();

    ext->state = UGD_STATE_NULL;
    lv_obj_del(ext->obj_confirm);
}

static void upgrade_update_confirm_create(void)
{
    lv_obj_t * par = upgrade_get_obj();
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    lv_obj_t * obj = lv_obj_create(par, NULL);
    lv_obj_set_size(obj, lv_obj_get_width(par), lv_obj_get_height(par));
    ext->obj_confirm = obj;

    lv_obj_t * label = lv_label_create(obj, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20_gray);
    lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_click(label, false);
    lv_label_set_text_id(label, WATCH_TEXT_ID_SYSTEM_UPG);
    lv_obj_align(label, obj, LV_ALIGN_IN_TOP_MID, 0, 10);

    label = lv_label_create(obj, NULL);
    lv_label_set_align(label, LV_LABEL_ALIGN_LEFT);
    lv_obj_set_click(label, false);
    lv_label_set_text_id(label, WATCH_TEXT_ID_CONFIRM_UPGRADE);
    lv_obj_align(label, obj, LV_ALIGN_IN_LEFT_MID, 20, -40);

    lv_obj_t  * btn = lv_imgbtn_create(obj, NULL);
    lv_imgbtn_set_src(btn, LV_BTN_STATE_RELEASED, ICON_CONFIRM_BIG);
    lv_imgbtn_set_src(btn, LV_BTN_STATE_PRESSED, ICON_CONFIRM_BIG);
    lv_obj_set_event_cb(btn, upgrade_confirm_btn_action);
    lv_watch_obj_add_element(btn);
    lv_obj_align(btn, obj, LV_ALIGN_IN_BOTTOM_LEFT, 20, -20);

    btn = lv_imgbtn_create(obj, NULL);
    lv_imgbtn_set_src(btn, LV_BTN_STATE_RELEASED, ICON_CANCEL_BIG);
    lv_imgbtn_set_src(btn, LV_BTN_STATE_PRESSED, ICON_CANCEL_BIG);
    lv_obj_set_event_cb(btn, upgrade_cancel_btn_action);
    lv_watch_obj_add_element(btn);
    lv_obj_align(btn, obj, LV_ALIGN_IN_BOTTOM_RIGHT, -20, -20);
}

static void upgrade_no_update_create(void)
{
    lv_obj_t * par = upgrade_get_obj();
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    lv_obj_t * obj = lv_obj_create(par, NULL);
    ext->obj_no_update = obj;

    lv_obj_set_size(obj, lv_obj_get_width(par), lv_obj_get_height(par));
    lv_obj_add_style(obj, LV_LABEL_PART_MAIN, &lv_style_transp_tight);

    lv_obj_t * cont = lv_cont_create(obj, NULL);
    lv_obj_add_style(cont, LV_LABEL_PART_MAIN, &lv_watch_cont_opa1);
    lv_obj_set_size(cont, 204, 44);
    lv_obj_align(cont, obj, LV_ALIGN_CENTER, 0, -12);
    lv_cont_set_layout(cont, LV_LAYOUT_CENTER);
    lv_obj_set_click(cont, false);

    lv_obj_t * label = lv_label_create(cont, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
    lv_label_set_text_id(label, WATCH_TEXT_ID_NO_UPDATE);
    lv_obj_set_click(label, false);

    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_var(&a, obj);
    lv_anim_set_ready_cb(&a, (lv_anim_ready_cb_t)upgrade_no_update_anim_end);
    lv_anim_set_time(&a, 1000);
    lv_anim_start(&a);
}

static void upgrade_no_update_anim_end(lv_obj_t * anim)
{
    (void)anim;

    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    lv_obj_del(ext->obj_no_update);
}

#if !UPGRADE_FOTA_GS
static void upgrade_download_progress_cb(void * para)
{
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();
    if(NULL == ext)  return;

    static uint8_t percent = 10;
    upgrade_download_percent_ind(percent);

    if(100 == percent) {
        percent = 0;
        Hal_Timer_Stop(ext->download_timer_id);
        ext->state = UGD_STATE_NULL;

        upgrade_restart_ind();
    } else {
        percent += 10;
    }
}
#endif

static void upgrade_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();

    watch_set_suspend_enable(true, ACT_ID_UPGRADE, 0);

#if !UPGRADE_FOTA_GS
    lv_upgrade_obj_ext_t * ext = upgrade_get_ext();

    if((NULL != ext) && (NULL != ext->download_timer_id)) {
        Hal_Timer_Stop(ext->download_timer_id);
    }
#endif
}

#if UPGRADE_FOTA_GS
static void upgrade_check_version_ind(FotaVersionInfo * version)
{
    if(version && version->versionName) {
        printf("%s: %s\n", __FUNCTION__, version->versionName);
    } else {
        printf("%s: no new version\n", __FUNCTION__);
    }

    mmi_msg_fota_check_version_ind_t * msg;
    msg = (mmi_msg_fota_check_version_ind_t *)lv_mem_alloc(sizeof(mmi_msg_fota_check_version_ind_t));
    msg->header.MsgId = MMI_FOTA_CHECK_VERSION_IND;
    msg->version = version;

    Hal_Send_Message((TASK_ID)gui_task_id, (void *)msg);
}

static void upgrade_download_percent_ind(INT32 percent)
{
    printf("%s: %d\n", __FUNCTION__, percent);

    mmi_msg_fota_download_percent_ind_t * msg;
    msg = (mmi_msg_fota_download_percent_ind_t *)lv_mem_alloc(sizeof(mmi_msg_fota_download_percent_ind_t));
    msg->header.MsgId = MMI_FOTA_DOWNLOAD_PERCENT_IND;
    msg->percent = percent;

    Hal_Send_Message((TASK_ID)gui_task_id, (void *)msg);
}

static void upgrade_restart_ind(void)
{
    printf("%s\n", __FUNCTION__);
    mmi_msg_fota_restart_ind_t * msg;
    msg = (mmi_msg_fota_restart_ind_t *)lv_mem_alloc(sizeof(mmi_msg_fota_restart_ind_t));
    msg->header.MsgId = MMI_FOTA_RESTART_IND;

    Hal_Send_Message((TASK_ID)gui_task_id, (void *)msg);
}

static void upgrade_result_ind(INT32 result)
{
    printf("%s: %d\n", __FUNCTION__, result);
    mmi_msg_fota_result_ind_t * msg;
    msg = (mmi_msg_fota_result_ind_t *)lv_mem_alloc(sizeof(mmi_msg_fota_result_ind_t));
    msg->header.MsgId = MMI_FOTA_RESULT_IND;
    msg->result = result;

    Hal_Send_Message((TASK_ID)gui_task_id, (void *)msg);
}

#else

static void upgrade_check_version_ind(FotaVersionInfo * version)
{
    upgrade_check_version_ind_handler(version);
}

static void upgrade_download_percent_ind(INT32 percent)
{
    upgrade_download_percent_ind_handler(percent);
}

static void upgrade_restart_ind(void)
{
    upgrade_restart_ind_handler();
}

static void upgrade_result_ind(INT32 result)
{
    upgrade_result_ind_handler(result);
}

#endif

#endif /*USE_LV_WATCH_UPGRADE*/
